package com.xci.sys.api;

import com.google.code.kaptcha.Producer;
import com.xci.core.annotation.AllowAnonymous;
import com.xci.core.annotation.Authorize;
import com.xci.core.base.ApiController;
import com.xci.core.base.PageList;
import com.xci.core.base.RestMessage;
import com.xci.core.domain.PageModel;
import com.xci.core.domain.SysUserSimple;
import com.xci.core.exceptions.AppException;
import com.xci.core.helper.ExcelHelper;
import com.xci.core.helper.Helper;
import com.xci.core.internal.Const;
import com.xci.sys.entity.SysUser;
import com.xci.sys.filter.UserFilter;
import com.xci.sys.service.LockUserService;
import com.xci.sys.service.UserService;
import io.swagger.annotations.*;
import org.springframework.cache.Cache;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.List;

/**
 * 用户接口
 * @author 吕艳阳
 */
@ApiSort(2)
@Api(tags = "用户接口")
@Authorize
@RestController
@RequestMapping(value = "/api/sys/user", produces = Const.P_JSON)
public class UserApiController extends ApiController {
    @Resource
    private UserService userService;//用户服务
    @Resource
    private LockUserService lockUserService;//锁定用户服务
    @Resource
    private Producer captchaProducer;
    @Resource
    private Producer captchaProducerMath;
    @Resource
    private Cache captchaCache;//用户验证码缓存

    @ApiOperationSupport(order = 1)
    @ApiOperation(value = "用户登录")
    @ApiImplicitParams({
           @ApiImplicitParam(name = "account", value = "用户账号", required = true),
           @ApiImplicitParam(name = "password", value = "用户密码", required = true),
           @ApiImplicitParam(name = "captcha", value = "验证码")
    })
    @AllowAnonymous
    @PostMapping("/login")
    public RestMessage<SysUser> login(String account, String password, String captcha) {
        return userService.login(account, password, captcha);
    }

    @ApiOperationSupport(order = 2)
    @ApiOperation(value = "用户注销")
    @ApiImplicitParam(name = "id", value = "用户主键", required = true)
    @PostMapping("/logout/{id}")
    public RestMessage logout(@PathVariable String id) {
        return userService.logout(id);
    }

    @ApiOperationSupport(order = 3)
    @ApiOperation(value = "账户验证")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "account", value = "用户账号", required = true),
            @ApiImplicitParam(name = "password", value = "用户密码", required = true),
            @ApiImplicitParam(name = "captcha", value = "验证码")
    })
    @AllowAnonymous
    @PostMapping("/validUser")
    public RestMessage validUser(String account, String password, String captcha) {
        RestMessage<SysUser> result = userService.login(account, password, captcha);
        if(result.isSuccess()){
            return RestMessage.success();
        }
        return RestMessage.fail(result.getMsg());
    }

    @ApiOperationSupport(order = 4)
    @ApiOperation(value = "检查账号登录是否需要验证码")
    @ApiImplicitParam(name = "account", value = "用户账号", required = true)
    @AllowAnonymous
    @PostMapping("/requireCaptcha")
    public RestMessage requireCaptcha(String account) {
        if(lockUserService.requireCaptcha(account)) {
            return RestMessage.success();
        }
        return RestMessage.fail();
    }

    @ApiOperationSupport(order = 5)
    @ApiOperation(value = "生成验证码")
    @ApiImplicitParams({
           @ApiImplicitParam(name = "account", value = "账号", required = true),
           @ApiImplicitParam(name = "type", allowableValues = "math,char")
    })
    @AllowAnonymous
    @PostMapping(value = "/captcha", produces = {Const.PRO_JPEG, Const.P_JSON})
    public void captcha(String account, String type, HttpServletResponse response) {
        if(Helper.isBlank(account)) {
            throw new AppException("请指定用户账号");
        }
        if(Helper.isBlank(type)) {
            type = "math";
        }
        ServletOutputStream out = null;
        try {
            response.setDateHeader("Expires", 0);
            response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
            response.addHeader("Cache-Control", "post-check=0, pre-check=0");
            response.setHeader("Pragma", "no-cache");
            response.setContentType("image/jpeg");

            String capStr, code;
            BufferedImage bi;
            if("math".equals(type)) {
                String capText = captchaProducerMath.createText();
                capStr = capText.substring(0, capText.lastIndexOf("@"));
                code = capText.substring(capText.lastIndexOf("@") + 1);
                bi = captchaProducerMath.createImage(capStr);
            } else {
                capStr = code = captchaProducer.createText();
                bi = captchaProducer.createImage(capStr);
            }

            captchaCache.put(account, code);
            out = response.getOutputStream();
            ImageIO.write(bi, "jpg", out);
            out.flush();
        } catch(Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if(out != null) {
                    out.close();
                }
            } catch(IOException e) {
                e.printStackTrace();
            }
        }
    }

    @ApiOperationSupport(order = 6)
    @ApiOperation(value = "新建用户")
    @Authorize(code = "sys.user.insert")
    @PostMapping("/insert")
    public RestMessage insert(@RequestBody SysUser entity) {
        return userService.insert(entity);
    }

    @ApiOperationSupport(order = 7)
    @ApiOperation(value = "修改用户")
    @Authorize(code = "sys.user.update")
    @PostMapping("/update")
    public RestMessage update(@RequestBody SysUser entity) {
        return userService.update(entity);
    }

    @ApiOperationSupport(order = 8)
    @ApiOperation(value = "修改用户状态")
    @ApiImplicitParams({@ApiImplicitParam(name = "ids", value = "用户主键字符串", required = true), @ApiImplicitParam(name = "status", value = "用户状态", required = true)})
    @Authorize(code = "sys.user.updateStatus")
    @PostMapping("/updateStatus")
    public RestMessage updateStatus(String ids, Boolean status) {
        return userService.updateStatus(ids, status);
    }

    @ApiOperationSupport(order = 9)
    @ApiOperation(value = "修改用户密码")
    @ApiImplicitParams({@ApiImplicitParam(name = "id", value = "用户主键", required = true), @ApiImplicitParam(name = "currentPassword", value = "当前密码", required = true), @ApiImplicitParam(name = "newPassword", value = "新密码", required = true)})
    @PostMapping("/modifyPassword")
    public RestMessage modifyPassword(String id, String currentPassword, String newPassword) {
        return userService.modifyPassword(id, currentPassword, newPassword);
    }

    @ApiOperationSupport(order = 10)
    @ApiOperation(value = "重置用户密码")
    @ApiImplicitParams({@ApiImplicitParam(name = "ids", value = "用户主键数组", required = true), @ApiImplicitParam(name = "newPassword", value = "新密码", required = true)})
    @Authorize(code = "sys.user.revisePassword")
    @PostMapping("/revisePassword")
    public RestMessage revisePassword(String ids, String newPassword) {
        return userService.revisePassword(ids, newPassword);
    }

    @ApiOperationSupport(order = 11)
    @ApiOperation(value = "删除用户")
    @ApiImplicitParam(name = "ids", value = "用户主键字符串", required = true)
    @Authorize(code = "sys.user.delete")
    @PostMapping("/delete")
    public RestMessage delete(String ids) {
        return userService.delete(ids);
    }


    @ApiOperationSupport(order = 12)
    @ApiOperation(value = "检查用户主键是否存在")
    @ApiImplicitParam(name = "id", value = "用户主键", required = true)
    @PostMapping("/existById/{id}")
    public RestMessage<Boolean> existById(@PathVariable String id){
        return RestMessage.result(userService.existById(id));
    }

    @ApiOperationSupport(order = 13)
    @ApiOperation(value = "检查机构主键是否存在")
    @ApiImplicitParam(name = "deptId", value = "机构主键", required = true)
    @PostMapping("/existByDeptId/{deptId}")
    public RestMessage<Boolean> existByDeptId(@PathVariable String deptId){
        return RestMessage.result(userService.existByDeptId(deptId));
    }

    @ApiOperationSupport(order = 14)
    @ApiOperation(value = "检查用户账号是否存在")
    @ApiImplicitParam(name = "account", value = "用户账号", required = true)
    @PostMapping("/existByAccount/{account}")
    public RestMessage<Boolean> existByAccount(@PathVariable String account) {
        return RestMessage.result(userService.existByAccount(account));
    }

    @ApiOperationSupport(order = 15)
    @ApiOperation(value = "查询单个用户")
    @ApiImplicitParam(name = "id", value = "用户主键", required = true)
    @PostMapping("/selectById/{id}")
    public RestMessage<SysUser> selectById(@PathVariable String id) {
        return RestMessage.success(userService.selectById(id));
    }

    @ApiOperationSupport(order = 16)
    @ApiOperation(value = "根据户账号查询单个用户")
    @ApiImplicitParam(name = "account", value = "用户账号", required = true)
    @PostMapping("/selectByAccount/{account}")
    public RestMessage<SysUser> selectByAccount(@PathVariable String account) {
        return RestMessage.success(userService.selectByAccount(account));
    }

    @ApiOperationSupport(order = 17)
    @ApiOperation(value = "查询简单用户分页列表")
    @PostMapping("/selectSimplePageList")
    public RestMessage<PageList<SysUserSimple>> selectSimplePageList(UserFilter filter,PageModel p) {
        return RestMessage.success(PageList.of(userService.selectSimplePageList(filter)));
    }

    @ApiOperationSupport(order = 18)
    @ApiOperation(value = "查询简单用户列表")
    @PostMapping("/selectSimpleList")
    public RestMessage<List<SysUserSimple>> selectSimpleList(UserFilter filter) {
        return RestMessage.success(userService.selectSimpleList(filter));
    }

    @ApiOperationSupport(order = 19)
    @ApiOperation(value = "查询用户分页列表")
    @PostMapping("/selectPageList")
    public RestMessage<PageList<SysUser>> selectPageList(UserFilter filter,PageModel p) {
        return RestMessage.success(PageList.of(userService.selectPageList(filter)));
    }

    @ApiOperationSupport(order = 20)
    @ApiOperation(value = "查询用户列表")
    @PostMapping("/selectList")
    public RestMessage<List<SysUser>> selectList(UserFilter filter) {
        return RestMessage.success(userService.selectList(filter));
    }

    @ApiOperationSupport(order = 19)
    @ApiOperation(value = "获取指定角色中已关联的用户列表")
    @ApiImplicitParam(name = "roleId", value = "角色主键", required = true)
    @PostMapping("/selectListByRoleId/{roleId}")
    public RestMessage<List<SysUser>> selectListByRoleId(@PathVariable String roleId) {
        return RestMessage.success(userService.selectListByRoleId(roleId));
    }

    @ApiOperationSupport(order = 19)
    @ApiOperation(value = "获取指定角色中已关联的用户分页列表")
    @ApiImplicitParam(name = "roleId", value = "角色主键", required = true)
    @PostMapping("/selectPageListByRoleId/{roleId}")
    public RestMessage<PageList<SysUser>> selectPageListByRoleId(@PathVariable String roleId,PageModel p) {
        return RestMessage.success(PageList.of(userService.selectPageListByRoleId(roleId)));
    }

    @ApiOperationSupport(order = 19)
    @ApiOperation(value = "获取指定机构中已关联的用户列表")
    @ApiImplicitParam(name = "deptId", value = "机构主键", required = true)
    @PostMapping("/selectListByDeptId/{deptId}")
    public RestMessage<List<SysUser>> selectListByDeptId(@PathVariable String deptId) {
        return RestMessage.success(userService.selectListByDeptId(deptId));
    }

    @ApiOperationSupport(order = 19)
    @ApiOperation(value = "获取指定机构中已关联的用户分页列表")
    @ApiImplicitParam(name = "deptId", value = "机构主键", required = true)
    @PostMapping("/selectPageListByDeptId/{deptId}")
    public RestMessage<PageList<SysUser>> selectPageListByDeptId(@PathVariable String deptId,PageModel p) {
        return RestMessage.success(PageList.of(userService.selectPageListByDeptId(deptId)));
    }

    @ApiOperationSupport(order = 21)
    @ApiOperation(value = "导出用户列表")
    @ApiImplicitParam(name = "fieldNames", value = "导出字段名字符串")
    @Authorize(code = "sys.user.export")
    @PostMapping(value = "/export", produces = {Const.P_OCTET, Const.P_JSON})
    public void export(UserFilter filter, @RequestParam(required = false) String fieldNames) {
        ExcelHelper.exportWeb(userService.selectList(filter), SysUser.class, "系统用户列表",fieldNames);
    }

    @ApiOperationSupport(order = 22)
    @ApiOperation(value = "获取用户导出字段")
    @PostMapping(value = "/exportNames")
    public RestMessage<List<String>> exportNames() {
        return RestMessage.success(ExcelHelper.getExcelFiledNames(SysUser.class));
    }

    @ApiOperationSupport(order = 23)
    @ApiOperation(value = "刷新用户缓存")
    @Authorize(code = "sys.user.refreshCache")
    @PostMapping(value = "/refreshCache")
    public RestMessage refreshCache() {
        userService.refreshCache();
        return RestMessage.success();
    }
}